/*
 * FillLayout.java
 *
 * Created on 2004/05/06 +0900
 *
 * $Revision: 59 $
 * $Date: 2008-12-28 19:22:21 +0000 (Sun, 28 Dec 2008) $
 */

package org.gikolet.framework.ui;

import org.gikolet.framework.util.Assert;

/**
 * @author Tetsutaro (latest modification by $Author: tetsutaro.ss $)
 * @version $Revision: 59 $ $Date: 2008-12-28 19:22:21 +0000 (Sun, 28 Dec 2008) $
 */
public class FillLayout implements Layout {
    public static final int HORIZONTAL = 0;
    public static final int VERTICAL = 1;

    private int type;
    private int marginWidth;
    private int marginHeight;
    private int spacing;

    public FillLayout() {
	this(HORIZONTAL, 0, 0, 0);
    }

    public FillLayout(int type, int marginWidth, int marginHeight, int spacing) {
	setType(type);
	setMargin(marginWidth, marginHeight);
	setSpacing(spacing);
    }

    public int getType() {
	return this.type;
    }

    public void setType(int type) {
	Assert.isTrue(type >= HORIZONTAL);
	Assert.isTrue(type <= VERTICAL);

	this.type = type;
    }

    public int getMarginWidth() {
	return this.marginWidth;
    }

    public int getMarginheight() {
	return this.marginHeight;
    }

    public void setMargin(int marginWidth, int marginHeight) {
	Assert.isTrue(0 <= marginWidth);
	Assert.isTrue(0 <= marginHeight);

	this.marginWidth = marginWidth;
	this.marginHeight = marginHeight;
    }

    /**
     * spacingを取得。
     *
     * @return spacing
     */
    public int getSpacing() {
	return spacing;
    }

    /**
     * spacingを設定。
     *
     * @param spacing
     *            spacing
     */
    public void setSpacing(int spacing) {
	this.spacing = spacing;
    }

    public Dimension getPreferredLayoutSize(Widget widget, int hintWidth,
	    int hintHeight) {

	int maxWidth = Widget.DEFAULT_LAYOUT, maxHeight = Widget.DEFAULT_LAYOUT;

	if (hintWidth != Widget.DEFAULT_LAYOUT) {

	    int w = hintWidth - this.marginWidth * 2 - widget.getLeftInset()
		    - widget.getRightInset();

	    if (type == HORIZONTAL) {
		w -= (widget.getWidgetCount() - 1) * this.spacing;
		maxWidth = w / widget.getWidgetCount();
	    } else {
		maxWidth = w;
	    }
	}
	if (hintHeight != Widget.DEFAULT_LAYOUT) {
	    int h = hintHeight - this.marginHeight * 2 - widget.getTopInset()
		    - widget.getBottomInset();

	    if (type != HORIZONTAL) {
		h -= (widget.getWidgetCount() - 1) * this.spacing;
		maxHeight = h / widget.getWidgetCount();
	    } else {
		maxHeight = h;
	    }
	}
	for (int i = 0; i < widget.getWidgetCount(); i++) {
	    Widget child = widget.getWidget(i);
	    Dimension size = child.getPreferredSize(maxWidth, maxHeight);
	    if (hintWidth == Widget.DEFAULT_LAYOUT) {
		maxWidth = Math.max(maxWidth, size.getWidth());
	    }
	    if (hintHeight == Widget.DEFAULT_LAYOUT) {
		maxHeight = Math.max(maxHeight, size.getHeight());
	    }
	}
	int width = 0, height = 0;
	if (this.type == HORIZONTAL) {
	    width = widget.getWidgetCount() * maxWidth;
	    if (widget.getWidgetCount() != 0) {
		width += (widget.getWidgetCount() - 1) * this.spacing;
	    }
	    height = maxHeight;
	} else {
	    width = maxWidth;
	    height = widget.getWidgetCount() * maxHeight;
	    if (widget.getWidgetCount() != 0) {
		height += (widget.getWidgetCount() - 1) * this.spacing;
	    }
	}
	width += this.marginWidth * 2 + widget.getLeftInset()
		+ widget.getRightInset();
	height += this.marginHeight * 2 + widget.getTopInset()
		+ widget.getBottomInset();

	return new Dimension(width, height);
    }

    public void layout(Widget widget) {

	Rectangle rect = widget.getClientArea();

	if (widget.getWidgetCount() == 0) {
	    return;
	}
	int width = rect.getWidth() - this.marginWidth * 2;
	int height = rect.getHeight() - this.marginHeight * 2;

	if (this.type == HORIZONTAL) {
	    width -= (widget.getWidgetCount() - 1) * this.spacing;

	    int x = rect.getX() + this.marginWidth, extra = width
		    % widget.getWidgetCount();
	    int y = rect.getY() + this.marginHeight, cellWidth = width
		    / widget.getWidgetCount();

	    for (int i = 0; i < widget.getWidgetCount(); i++) {
		Widget child = widget.getWidget(i);
		int childWidth = cellWidth;
		if (i == 0) {
		    childWidth += extra / 2;
		} else if (i == widget.getWidgetCount() - 1) {
		    childWidth += (extra + 1) / 2;
		}
		child.setBounds(x, y, childWidth, height);
		x += childWidth + this.spacing;
	    }
	} else {
	    height -= (widget.getWidgetCount() - 1) * this.spacing;

	    int x = rect.getX() + this.marginWidth, cellHeight = height
		    / widget.getWidgetCount();
	    int y = rect.getY() + this.marginHeight, extra = height
		    % widget.getWidgetCount();

	    for (int i = 0; i < widget.getWidgetCount(); i++) {
		Widget child = widget.getWidget(i);
		int childHeight = cellHeight;
		if (i == 0) {
		    childHeight += extra / 2;
		} else if (i == widget.getWidgetCount() - 1) {
		    childHeight += (extra + 1) / 2;
		}
		child.setBounds(x, y, width, childHeight);
		y += childHeight + this.spacing;
	    }
	}
    }
}
